<?php
//+-------------------------------------------------------------
//| 验证类基类
//+-------------------------------------------------------------
//| Author Liu LianSen <liansen@d3zz.com> 
//+-------------------------------------------------------------
//| Date 2017-10-10
//+-------------------------------------------------------------
namespace app\common\validate;

use think\Validate as Base;

class Validate extends Base
{

    /**
     * 身份证规则
     * @param $val
     * @return bool
     */
    protected function idCardNo($val)
    {
        if(!is_string($val)) return false;
        if(strlen($val) == 15){
            return !!preg_match('/^\d{6}\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}$/', $val);
        }else{
            return $this->preg18($val) && $this->validateCheckCode($val);
        }
    }


    /**
     * @param $id
     * @return int
     */
    protected function preg18($id)
    {
        return preg_match('/^\d{6}(19|20)\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/', $id);
    }

    /**
     * @param $id17
     * @return mixed
     */
    private function getIDCardVerifyNumber($id17)
    {
        // 加权因子
        $factor = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
        // 校验码对应值
        $verify_number_list = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
        $checksum = 0;
        for ($i = 0; $i < strlen($id17); $i++) {
            $checksum += substr($id17, $i, 1) * $factor[$i];
        }
        $mod = $checksum % 11;
        $verify_number = $verify_number_list[$mod];
        return $verify_number;
    }

    /**
     * @param $id
     * @return bool
     */
    protected function validateCheckCode($id)
    {
        $pid = strtoupper($id);
        $iYear = substr($pid, 6, 4);
        $iMonth = substr($pid, 10, 2);
        $iDay = substr($pid, 12, 2);
        if (checkdate($iMonth, $iDay, $iYear)) {
            $id17 = substr($pid, 0, 17);  //身份证证号前17位
            if ($this->getIDCardVerifyNumber($id17) != substr($pid, -1)) {
                return false;
            } else {
                return true;
            }
        }
    }


}